package com.alks.function.controller.task;


import com.alks.common.aop.RedisLock;
import com.alks.common.data.thread.UserIdThread;
import com.alks.common.utils.beanutils.BeanUtil;
import com.alks.common.utils.beanutils.ObjectUtils;
import com.alks.entity.data.entity.PcStitchDetail;
import com.alks.entity.data.entity.PcStitchDetailAttach;
import com.alks.entity.data.response.ResponseInfo;
import com.alks.entity.exception.ServiceErrorException;
import com.alks.function.data.dto.chengKong.produce.*;
import com.alks.function.data.dto.pcfactoryquery.PcStitchDetaiaAttachlDto;
import com.alks.function.data.request.stockdept.pcfactorystockwork.PcCodeRequest;
import com.alks.function.data.request.stockdept.pcfactorystockwork.StitchIORequest;
import com.alks.function.mapper.chengKong.PcLotHeadMapper;
import com.alks.function.mapper.pcfactoryquery.FT_QR_PcStitchDetailAttachMapper;
import com.alks.function.mapper.pcfactoryquery.FT_QR_PcStitchDetailMapper;
import com.alks.function.mapper.pcfactoryquery.FT_QR_PcStitchStatusMapper;
import com.alks.function.service.pcfactoryquery.IPcStitchDetailService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * 针车
 * 定时统计鞋面库存
 */
@Component
@Slf4j
@EnableScheduling
@EnableAsync
public class StitchTask {

    @Autowired
    private FT_QR_PcStitchStatusMapper  pcStitchStatusMapper;

    @Autowired
    private FT_QR_PcStitchDetailMapper pcStitchDetailMapper;

    @Autowired
    private  FT_QR_PcStitchDetailAttachMapper pcStitchDetailAttachMapper;

    @Autowired
    private PcLotHeadMapper pcLotHeadMapper;

    @Autowired
    private IPcStitchDetailService stitchService;

    @Autowired
    FT_QR_PcStitchDetailMapper stitchMapper;

    /**
     * 定时统计 PC_STITCH_DETAIL_ATTACH 数据到 pcStitchStatus
     */
    @Async("TaskExecutor")
    @Scheduled(cron = "0 30 1 * * ?") // 每天1点半
    @Transactional
    @RedisLock(key = "updateStitchStatus")
    public void ScheduleInsertPcStitchStatus(){
        try{
        log.info("定时任务执行开始,鞋面库存 pcStitchStatus更新开始：");
        stitchService.updateStitchStatus();
        log.info("定时任务执行成功, 鞋面库存更新完成！");
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 定时更新 PC_STITCH_COLLECT_DEPT_HEAD 里面的人数
     */
    @Async("TaskExecutor")
    @Scheduled(cron = "0 0 1 * * ?")
    @Transactional
    @RedisLock(key = "updateStitchDeptPeoplo")
    public void ScheduleInsertStitchDeptPeoplo(){
        try{
            log.info("定时任务执行开始,定时统计 PC_STITCH_COLLECT_DEPT_HEAD 里面的人数：");
            stitchMapper.updateStitchDeptPeoplo();
            log.info("定时任务执行成功, 定时统计 PC_STITCH_COLLECT_DEPT_HEAD 里面的人数完成！");
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 清洗pc_stitch_detail_attach 表数据 （用量）
     * 同步 pcStitchDetail 数据到 StitchDetailAttach
     */
    @Async("TaskExecutor")
    //@Scheduled(initialDelay = 5000, fixedRate = 86400000) // 5秒后首次执行，之后每天执行一
    @Scheduled(cron = "0 0 1 * * ?") // 每天凌晨1点执行
    @Transactional
    @RedisLock(key = "task:PcStitchStatusTask.ScheduleUpdatepcStitchDetailAttach")
    public void ScheduleUpdatepcStitchDetailAttach(){
        try{
            log.info("定时任务执行开始,pcStitchDetailAttach 更新开始：");
            //1.先查询指令+公司+出入库类型+入库时间 种 pcStitchDetail 和 StitchDetailAttach 的总数据有差异的更新数据
            List<PcStitchDetaiaAttachlDto> details= pcStitchDetailMapper.queryStitchAndAttach();
            if(ObjectUtils.isEmpty(details)){
                throw new ServiceErrorException("没有需要清洗的数据");
            }

            //2.把两者用量不同的数据取出来，根据数据删除
            List<String> slipNoList2 = details.stream()
                    .filter(item -> item.getQty() != 0)
                    .map(PcStitchDetaiaAttachlDto::getSlipNo)
                    .collect(Collectors.toList());
            if(ObjectUtils.isNotEmpty(slipNoList2)){
                pcStitchDetailAttachMapper.deleteBatchBySlipNos(slipNoList2);
            }

            List<String> slipNoList = details.stream()
                    .map(PcStitchDetaiaAttachlDto::getSlipNo)
                    .collect(Collectors.toList());

            //3.新增数据
            //批量根据slipNo 查询pcStitchDetail 数据
            List<PcStitchDetail> pcStitchDetailList = pcStitchDetailMapper.queryStitchDetailBySlipNos(slipNoList);
            //遍历新增数据
            if (ObjectUtils.isNotEmpty(pcStitchDetailList)){
                for (PcStitchDetail detail : pcStitchDetailList) {
                    /*更新detailAttach数据*/
                    StitchIORequest request = BeanUtil.copyBean(detail, StitchIORequest.class);
                    List<PcCodeAndStitchDto> codeAndStitchList = assembleData(request);
                    if (ObjectUtils.isEmpty(codeAndStitchList)) {
                        throw new ServiceErrorException("没有数据可更新");
                    }
                    // 提取所有需要的 qtyFlag
                    List<String> qtyList = codeAndStitchList.stream()
                            .map(PcCodeAndStitchDto::getQtyFlag)
                            .collect(Collectors.toList());
                    // 根据qty去查询鞋码
                    PcCodeRequest pcCodeRequest = new PcCodeRequest();
                    pcCodeRequest.setCompanyId(detail.getCompanyId());
                    pcCodeRequest.setLotNo(request.getLotNo());
                    pcCodeRequest.setQtyFlagList(qtyList);
                    List<PcLotDetailDto2> codeDetailList = pcLotHeadMapper.getCodeDetails5(pcCodeRequest);
                    // 使用 Map 提高查找效率》》
                    Map<String, PcLotDetailDto2> detailMap = codeDetailList.stream()
                            .collect(Collectors.toMap(PcLotDetailDto2::getQtyFlag, dto -> dto));
                    // 更新 codeAndStitchList 中的对象
                    List<PcStitchDetailAttach> attachList = new ArrayList<>();
                    for (PcCodeAndStitchDto pcCodeAndStitchDto : codeAndStitchList) {
                        PcStitchDetailAttach detailAttach = new PcStitchDetailAttach();
                        BeanUtil.copyProperties(pcCodeAndStitchDto, detailAttach);
                        PcLotDetailDto2 detailDto2 = detailMap.get(pcCodeAndStitchDto.getQtyFlag());
                        if (detailDto2 != null) {
                            //pcCodeAndStitchDto.setSeqNo(detailDto2.getSeqNo());
                            //pcCodeAndStitchDto.setSizeNo(detailDto2.getSizeNo());
                            detailAttach.setSeqNo(Integer.valueOf(detailDto2.getSeqNo()));
                            detailAttach.setSizeNo(detailDto2.getSizeNo());
                        }
                        detailAttach.setCompanyId(detail.getCompanyId());
                        detailAttach.setSysUser(detail.getSysUser());
                        detailAttach.setSysDate(detail.getSysDate());
                        detailAttach.setUpdateUser("系统");
                        detailAttach.setUpdateDate(LocalDateTime.now());
                        detailAttach.setSlipNo(detail.getSlipNo());
                        detailAttach.setStkName(detail.getStkName());
                        detailAttach.setSlipType(detail.getSlipType());
                        detailAttach.setDeptName(detail.getDeptName());
                        attachList.add(detailAttach);
                    }

                    int count2 = pcStitchDetailAttachMapper.batchInsert(attachList);

                }
            }

            log.info("定时任务执行开始,pcStitchDetailAttach 清洗完成！");
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public List<PcCodeAndStitchDto> assembleData(StitchIORequest request) {
        //组装数据容器
        List<PcCodeAndStitchDto> codeAndStitchList = new ArrayList<>();
        // 获取所有声明的字段
        Field[] fields = request.getClass().getDeclaredFields();
        // 遍历所有字段，提取 qty 字段及其值
        for (Field field : fields) {
            if (field.getName().startsWith("qty") && field.getType() == Float.class) {
                field.setAccessible(true);
                try {
                    String fieldName = field.getName();
                    Float value = (Float) field.get(request);

                    if (value != null) {
                        PcCodeAndStitchDto codeAndStitchDto = new PcCodeAndStitchDto();
                        BeanUtil.copyProperties(request, codeAndStitchDto);
                        codeAndStitchDto.setQtyFlag(fieldName);
                        codeAndStitchDto.setQty(value);
                        codeAndStitchList.add(codeAndStitchDto);
                    }
                } catch (IllegalAccessException e) {
                    // 更好的异常处理，例如记录详细日志
                    throw new RuntimeException("反射访问字段失败: " + field.getName(), e);
                }
            }
        }
        return codeAndStitchList;
    }
}
